home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ultimate Screensaver
/
Ultimate Screen Savers Collection (CMS Distributing) (1996).ISO
/
saver3
/
xwsave1
/
flame.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-15
|
4KB
|
166 lines
#ifndef lint
static char sccsid[] = "@(#)flame.c 1.4 91/09/27 XLOCK";
#endif
/*-
* flame.c - recursive fractal cosmic flames.
*
* Copyright (c) 1991 by Patrick J. Naughton.
*
* See xlock.c for copying information.
*
* Revision History:
* 27-Jun-91: vary number of functions used.
* 24-Jun-91: fixed portability problem with integer mod (%).
* 06-Jun-91: Written. (received from Scott Graves, spot@cs.cmu.edu).
*/
#include "xlock.h"
#include <math.h>
#define MAXTOTAL 10000
#define MAXBATCH 10
#define MAXLEV 4
typedef struct {
double f[2][3][MAXLEV];/* three non-homogeneous transforms */
int max_levels;
int cur_level;
int snum;
int anum;
int width, height;
int num_points;
int total_points;
int pixcol;
Window win;
XPoint pts[MAXBATCH];
} flamestruct;
static flamestruct flames[MAXSCREENS];
static short
halfrandom(mv)
int mv;
{
static short lasthalf = 0;
unsigned long r;
if (lasthalf) {
r = lasthalf;
lasthalf = 0;
} else {
r = random();
lasthalf = r >> 16;
}
return r % mv;
}
void
initflame(win)
Window win;
{
flamestruct *fs = &flames[screen];
XWindowAttributes xwa;
XGetWindowAttributes(dsp, win, &xwa);
fs->width = xwa.width;
fs->height = xwa.height;
fs->max_levels = batchcount;
fs->win = win;
XSetForeground(dsp, Scr[screen].gc, BlackPixel(dsp, screen));
XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, fs->width, fs->height);
if (!mono && Scr[screen].npixels > 2) {
fs->pixcol = halfrandom(Scr[screen].npixels);
XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[fs->pixcol]);
} else {
XSetForeground(dsp, Scr[screen].gc, WhitePixel(dsp, screen));
}
}
static Bool
recurse(fs, x, y, l)
flamestruct *fs;
register double x, y;
register int l;
{
int /*xp, yp,*/ i;
double nx, ny;
if (l == fs->max_levels) {
fs->total_points++;
if (fs->total_points > MAXTOTAL) /* how long each fractal runs */
return False;
if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) {
/* xp = */ fs->pts[fs->num_points].x = (int) ((fs->width / 2)
* (x + 1.0));
/* yp = */ fs->pts[fs->num_points].y = (int) ((fs->height / 2)
* (y + 1.0));
fs->num_points++;
if (fs->num_points > MAXBATCH) { /* point buffer size */
XDrawPoints(dsp, fs->win, Scr[screen].gc, fs->pts,
fs->num_points, CoordModeOrigin);
fs->num_points = 0;
}
}
} else {
for (i = 0; i < fs->snum; i++) {
nx = fs->f[0][0][i] * x + fs->f[0][1][i] * y + fs->f[0][2][i];
ny = fs->f[1][0][i] * x + fs->f[1][1][i] * y + fs->f[1][2][i];
if (i < fs->anum) {
nx = sin(nx);
ny = sin(ny);
}
if (!recurse(fs, nx, ny, l + 1))
return False;
}
}
return True;
}
void
drawflame(win)
Window win;
{
flamestruct *fs = &flames[screen];
int i, j, k;
static alt = 0;
if (!(fs->cur_level++ % fs->max_levels)) {
XClearWindow(dsp, fs->win);
alt = !alt;
} else {
if (Scr[screen].npixels > 2) {
XSetForeground(dsp, Scr[screen].gc,
Scr[screen].pixels[fs->pixcol]);
if (--fs->pixcol < 0)
fs->pixcol = Scr[screen].npixels - 1;
}
}
/* number of functions */
fs->snum = 2 + (fs->cur_level % (MAXLEV - 1));
/* how many of them are of alternate form */
if (alt)
fs->anum = 0;
else
fs->anum = halfrandom(fs->snum) + 2;
/* 6 coefs per function */
for (k = 0; k < fs->snum; k++) {
for (i = 0; i < 2; i++)
for (j = 0; j < 3; j++)
fs->f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
}
fs->num_points = 0;
fs->total_points = 0;
(void) recurse(fs, 0.0, 0.0, 0);
XDrawPoints(dsp, win, Scr[screen].gc,
fs->pts, fs->num_points, CoordModeOrigin);
}